#pragma once

#include <functional>

#include "socket_utils.h"
#include "logging.h"

namespace Common {
  /// 发送/接收缓冲区的固定大小（64 MB）——需要根据业务吞吐量评估是否足够。
  constexpr size_t TCPBufferSize = 64 * 1024 * 1024;

  /**
   * @brief TCP socket 封装，负责 socket 的生命周期、缓冲区管理与回调触发。
   *
   * Logger 引用被显式传入，不允许默认构造/拷贝/移动，确保后台日志线程与队列
   * 的资源不会被多个实例共享导致竞态。
   */
  struct TCPSocket {
    explicit TCPSocket(Logger &logger)
        : logger_(logger) {
      // 初始化收发缓冲区，避免运行时频繁扩容造成抖动。
      outbound_data_.resize(TCPBufferSize);
      inbound_data_.resize(TCPBufferSize);
    }

    /**
     * @brief 根据配置连接或监听 TCP socket。
     *
     * @param ip           目标 IP（监听模式可留空）。
     * @param iface        网络接口名（监听模式需指定）。
     * @param port         目标端口。
     * @param is_listening 是否作为监听端口。
     * @return 返回创建的 socket 描述符；失败时触发 ASSERT 并终止。
     *
     * @note 底层调用 createSocket()，该函数会通过 Logger 异步输出详细参数与错误。
     */
    auto connect(const std::string &ip, const std::string &iface, int port, bool is_listening) -> int;

    /**
     * @brief 非阻塞地发送/接收数据，必要时触发回调。
     *
     * @return 若本次调用读取到了数据返回 true，否则返回 false。
     *
     * @details
     *  - 首先尝试读取（recvmsg），处理内核时间戳并将信息写入日志。
     *  - 若有待发送数据，则调用 send() 将缓冲区内容写出去，并记录日志。
     *  - 典型场景：由 IO 线程在 epoll 事件后调度。
     */
    auto sendAndRecv() noexcept -> bool;

    /**
     * @brief 将上层待发送的数据写入发送缓冲区。
     *
     * @param data 指向待发送内容。
     * @param len  数据长度。
     *
     * @note 只是拷贝到 outbound buffer；真正的发送在 sendAndRecv() 中完成。
     */
    auto send(const void *data, size_t len) noexcept -> void;

    /// 禁用默认构造与拷贝/移动，防止 Logger & socket 资源被不当共享。
    TCPSocket() = delete;
    TCPSocket(const TCPSocket &) = delete;
    TCPSocket(const TCPSocket &&) = delete;
    TCPSocket &operator=(const TCPSocket &) = delete;
    TCPSocket &operator=(const TCPSocket &&) = delete;

    /// 底层 socket 文件描述符。
    int socket_fd_ = -1;

    /// 发送缓冲区及有效数据长度游标。
    std::vector<char> outbound_data_;
    size_t next_send_valid_index_ = 0;

    /// 接收缓冲区及有效数据长度游标。
    std::vector<char> inbound_data_;
    size_t next_rcv_valid_index_ = 0;

    /// 远端地址信息，用于 recvmsg()/sendto() 等结构体传参。
    struct sockaddr_in socket_attrib_{};

    /// 用户自定义的收包回调（接收线程中触发）。Nanos 来自 time_utils。
    std::function<void(TCPSocket *s, Nanos rx_time)> recv_callback_ = nullptr;

    /// 辅助 Logger 输出当前时间，避免频繁构造临时字符串。
    std::string time_str_;

    /// 引用型 Logger，所有日志统一通过异步线程写盘。
    Logger &logger_;
  };
}  // namespace Common